#pragma once

#include <string>
#include <vector>
#include <unordered_map>
#include <atomic>
#include <fstream>

#include <cstring>
#include <cerrno>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>

#include <jsoncpp/json/json.h>

enum
{
    CodeEmpty = -3,
    Compile_Err, // 编译失败
    System_Call_Err,  // 系统调用失败
    Success   // 编译/运行成功
};

namespace TimeOper
{
    class time
    {
    public:
        // 获取秒级别的时间戳
        static std::string GetTimeStamp()
        {
            timeval tv;
            gettimeofday(&tv, nullptr);
            return std::to_string(tv.tv_sec);
        }
        // 获取毫秒级别的时间戳
        static std::string GetSusecondsTimeStamp()
        {
            timeval tv;
            gettimeofday(&tv, nullptr);
            return std::to_string(tv.tv_usec);
        }
    };
};

// 对文件的操作，如路径拼接、增添后缀
namespace FileOper
{
    const std::string temp_file_path = "./temp/";
    // 编译时需要的文件后缀
    const std::string src_name = ".cc";
    const std::string exe_name = ".exe";
    const std::string err_name = ".compile_err";
    // 运行时需要的文件后缀
    const std::string std_out = ".stdout";
    const std::string std_in = ".stdin";
    const std::string std_err = ".stderr";

    class File
    {
    public:
        // 拼接路径 file -> ../temp/file
        static std::string AddPath(const std::string &filename)
        {
            return temp_file_path + filename;
        }

// 编译时生成的临时文件 //

        // 形成.cc
        static std::string Src(const std::string &filename)
        {
            return AddPath(filename) + src_name;
        }

        // 形成.exe
        static std::string Exe(const std::string &filename)
        {
            return AddPath(filename) + exe_name;
        }

        // 形成.err
        static std::string Complie_Err(const std::string &filename)
        {
            return AddPath(filename) + err_name;
        }

// 运行时生成的临时文件 //

        //形成.stdout
        static std::string StdOut(const std::string &filename)
        {
            return AddPath(filename) + std_out;
        }

        //形成.stdin
        static std::string StdIn(const std::string &filename)
        {
            return AddPath(filename) + std_in;
        }
        
        //形成.stderr
        static std::string StdErr(const std::string &filename)
        {
            return AddPath(filename) + std_err;
        }

        // 判断.exe是否生成
        static bool IsFileExist(const std::string &filename)
        {
            struct stat statbuff;
            return stat(filename.c_str(), &statbuff) == 0;
            // 不可以穿nullptr，文件属性参数必须为非空参数
        }

// 拿到文件内容
        static bool GetfileMessage(const std::string &filename, std::string& message)
        {
            message.clear();

            std::ifstream in(filename, std::ios::in);
            if(!in.is_open()) return false;

            std::string temp;
            while(std::getline(in, temp))
            {
                message += temp;
                message += "\n";
            }
            
            in.close();
            return true;
        }
// 将内容写入文件
        static bool MessageToFile(const std::string& filename, const std::string& message)
        {
            std::ofstream out(filename, std::ios::out);
            if(!out.is_open()) return false;
            out.write(message.c_str(), message.size());
            out.close();
            return true;
        }

// 形成唯一的文件名, 利用毫秒级时间戳和原子性递增
        static std::string GetOwnFileName()
        {
            // 定义一个原子性的变量
            static std::atomic_uint am(0); 
            ++am; //原子性递增

            std::string time = TimeOper::time::GetSusecondsTimeStamp();
            return time + "_" + std::to_string(am);
        }

// 删除所有的临时文件
        static void DeleteTemp(const std::string& file)
        {
            ExistToDele(Src(file).c_str());
            ExistToDele(StdErr(file).c_str());
            ExistToDele(StdIn(file).c_str());
            ExistToDele(StdOut(file).c_str());
            ExistToDele(Exe(file).c_str());
            ExistToDele(Complie_Err(file).c_str());
        }
// 判断文件存在 -> 删除
        static void ExistToDele(const std::string& file)
        {
            if(IsFileExist(file))
                unlink(file.c_str());
        }
// 将信息使用Json序列化
        static std::string Serialize(int status, const std::string &message)
        {
            Json::Value out;
            out["status"] = status;
            out["result"] = message;
            Json::StyledWriter writer;
            std::string ser = writer.write(out);
            return ser;
        }
// 将response信息反序列化
        static void Deserialize(int& status, std::string &message, const std::string &response)
        {
            Json::Value in;
            Json::Reader reader;
            reader.parse(response, in);
            status = in["status"].asInt();
            message = in["result"].asString();
        }
// 分割字符串
        /* ******************************************************
         * message -> 要分隔的字符串
         * sep -> 分隔字符
         * content_group -> 分割后的字符串存放的内容组，这里保证提取到的个数一定为5个：【num, name, level, cpu, as】
         * ******************************************************/
        static void SepListLine(const std::string& message, const std::string& sep, std::vector<std::string>& content_group)
        {
            int begin = 0;
            int pos = message.find(sep, begin); 

            while(pos != std::string::npos)
            {
                content_group.push_back(message.substr(begin, pos - begin));
                begin = pos + sep.size();
                pos = message.find(sep, begin); 
            }

            pos = message.size();
            content_group.push_back(message.substr(begin, pos - begin));

        }

    private:
    };
};

namespace ns_sign_to_message
{
    std::unordered_map<int, std::string> signal_error_map = 
    {
        {1, "SIGHUP: Hangup detected on controlling terminal or death of controlling process"},
        {2, "SIGINT: Interrupt from keyboard"},
        {3, "SIGQUIT: Quit from keyboard"},
        {4, "SIGILL: Illegal Instruction"},
        {5, "SIGTRAP: Trace/breakpoint trap"},
        {6, "SIGABRT: Aborted"},
        {7, "SIGBUS: Bus error (bad memory access)"},
        {8, "SIGFPE: Floating point exception"},
        {9, "SIGKILL: Killed"},
        {10, "SIGUSR1: User-defined signal 1"},
        {11, "SIGSEGV: Segmentation fault"},
        {12, "SIGUSR2: User-defined signal 2"},
        {13, "SIGPIPE: Broken pipe"},
        {14, "SIGALRM: Alarm clock"},
        {15, "SIGTERM: Terminated"},
        {16, "SIGSTKFLT: Stack fault on coprocessor (unused)"},
        {17, "SIGCHLD: Child process has terminated or stopped"},
        {18, "SIGCONT: Continue executing, if stopped"},
        {19, "SIGSTOP: Stop executing (cannot be caught or ignored)"},
        {20, "SIGTSTP: Stop from keyboard"},
        {21, "SIGTTIN: Background process attempting read"},
        {22, "SIGTTOU: Background process attempting write"},
        {23, "SIGURG: Urgent data available on socket"},
        {24, "SIGXCPU: CPU time limit exceeded"},
        {25, "SIGXFSZ: File size limit exceeded"},
        {26, "SIGVTALRM: Virtual timer expired"},
        {27, "SIGPROF: Profiling timer expired"},
        {28, "SIGWINCH: Window size change"},
        {29, "SIGIO: I/O is possible on a descriptor"},
        {30, "SIGPWR: Power failure (unused)"},
        {31, "SIGSYS: Bad system call"},
    };
};